package cn.lili.controller.feign;

import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.SpringContextUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.kit.CashierSupport;
import cn.lili.modules.kit.Payment;
import cn.lili.modules.kit.RefundSupport;
import cn.lili.modules.order.order.client.OrderClient;
import cn.lili.modules.payment.client.PaymentClient;
import cn.lili.modules.payment.entity.dos.*;
import cn.lili.modules.payment.entity.dto.*;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.payment.entity.vo.OutOrderLogVO;
import cn.lili.modules.payment.sentine.PaymentSentinelHandler;
import cn.lili.modules.payment.service.CombinePaymentLogService;
import cn.lili.modules.payment.service.PaymentLogService;
import cn.lili.modules.payment.task.PaymentEveryDayTask;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.transaction.annotation.ShardingTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * 支付 feign client
 *
 * @author Chopper
 * @version v1.0 2021-12-07 19:07
 */
@RestController
@RequiredArgsConstructor
@Slf4j
public class PaymentFeignController implements PaymentClient {

    private final RefundSupport refundSupport;

    private final CashierSupport cashierSupport;

    private final PaymentSentinelHandler paymentSentinelHandler;

    private final PaymentEveryDayTask paymentEveryDayTask;

    private final PaymentLogService paymentLogService;

    private final CombinePaymentLogService combinePaymentLogService;

    private final OrderClient orderClient;

    @Override
    public CashierParam base(String paymentClientType) {
        return cashierSupport.cashierParam(paymentClientType);
    }

    @Override
    public ResultMessage<Object> generatePaymentForm(PayParam payParam) {
        return cashierSupport.generatePaymentForm(payParam);
    }


    @Override
    public RefundLog refund(RefundParam refundParam) {

        return refundSupport.refund(refundParam);
    }

    @Override
    public void offlinePay(PayParam payParam) {
        cashierSupport.generatePaymentForm(payParam);
    }

    @Override
    public PaymentSubsidies subsidies(SubsidiesParams subsidiesParams) {
        return cashierSupport.subsidies(subsidiesParams);
    }

    @Override
    public void everyMinuteExecute() {
        paymentSentinelHandler.backCheck();
    }

    @Override
    public void everyDayTask() {
        paymentEveryDayTask.execute();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OutOrderLogVO profitSharing(ProfitSharingRequestDTO profitSharingRequestDTO) {
        try {
            //如果时特殊订单 需先做特殊订单处理
            if (Boolean.TRUE.equals(profitSharingRequestDTO.getSpecialOrder())) {

                //获取支付日志
                PaymentLog paymentLog;

                //处理极端情况，客户支付0元，但是还需要分账
                if (profitSharingRequestDTO.getTotalAmount().equals(0D)) {
                    paymentLog = paymentLogService.generateZeroLog(profitSharingRequestDTO);
                } else {
                    //获取支付日志
                    paymentLog = paymentLogService.getPaymentLogByOrderSN(profitSharingRequestDTO.getOrderSn());
                }
                //对已有信息进行分账
                Payment payment = (Payment) SpringContextUtil.getBean(profitSharingRequestDTO.getPaymentMethodEnum().getPlugin());
                //分账给平台
                OutOrderLog outOrderLog = payment.profitSharingPlatform(paymentLog);

                //钱包支付 兜底测略，先将补差信息的金额分给平台
                Payment walletPlugin = (Payment) SpringContextUtil.getBean(PaymentMethodEnum.WALLET.getPlugin());
                //补差信息分账 分给平台
                walletPlugin.profitSharingSubsidies(outOrderLog);

                //剩下的交给钱包兜底，因为当前系统支付兜底都是由钱包支付进行：例如补差、或是分账
                return walletPlugin.specialProfitSharing(outOrderLog, profitSharingRequestDTO);

            }
            //普通分账直接处理
            else {
                Payment payment = (Payment) SpringContextUtil.getBean(profitSharingRequestDTO.getPaymentMethodEnum().getPlugin());
                return payment.profitSharing(profitSharingRequestDTO);
            }
        } catch (Exception e) {
            orderClient.updateProfitSharingOrderFlow(profitSharingRequestDTO.getOrderSn());
            orderClient.addOrderFlowProfitSharing(profitSharingRequestDTO.getOrderSn(),e.getMessage());
            log.error("ee=== ", e);
            throw new ServiceException(e.getMessage());
        }
    }

    @Override
    public void wechatBill() {
        paymentEveryDayTask.wechatBill();
    }

    @Override
    public PaymentUrbanSubstationCommission urbanSubstationCommission(UrbanSubstationCommissionParams params) {
        return cashierSupport.urbanSubstationCommission(params);
    }

    @Override
    public ResultMessage<Object> generatePaymentSceneForm(PayParam payParam) {
        return cashierSupport.generatePaymentSceneForm(payParam);
    }

    @Override
    public ResultMessage<Object> memberCastellan(UserPointUpdateDTO userPointUpdateDTO){
        return paymentLogService.memberCastellan(userPointUpdateDTO);
    }

    @Override
    public ResultMessage<Object> memberUnion(UserPointUpdateDTO userPointUpdateDTO){
        return paymentLogService.memberUnion(userPointUpdateDTO);
    }

    @Override
    public CombinePaymentLog getCombinePaymentLogByCombineOutTradeNo(String combineOutTradeNo) {
        return combinePaymentLogService.getCombinePaymentLogByCombineOutTradeNo(combineOutTradeNo);
    }

    @Override
    public PaymentLog getPaymentLogByOrderSN(String orderSN) {
        //获取支付日志
        PaymentLog paymentLog = paymentLogService.getPaymentLogByOrderSN(orderSN);
        return paymentLog;
    }
}
